package com.jamal2362.apktool.util.search;

import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import com.jamal2362.apktool.R;
import com.jamal2362.apktool.fragment.files.FilesAdapter;
import com.jamal2362.apktool.util.MUtil;
import com.jamal2362.apktool.util.Settings;

public class Search {
	public static final String[] textExt = new String[]{"txt", "xml", "conf", "prop", "cpp", "h", "java", "log", "json", "js", "php", "css", "py", "c", "smali", "cfg", "ini", "bat", "mf", "mtd", "lua", "htm", "html"};
	private static Context context;
	private static FilesAdapter refresh;
	private static List<String> mResult;
	private static RadioButton rb2;
	private static CheckBox cb;
	private static CheckBox cb2;
	private static LayoutInflater mInflater;
	private static boolean stopSearch;
	private static SearchHistory searchHistory;

	public Search(Context ctx, FilesAdapter refresh) {
		this.context = ctx;
		this.refresh = refresh;
		this.stopSearch = false;
		this.mInflater = LayoutInflater.from(context);
		this.searchHistory = new SearchHistory(context);
		clearResult();
	}

	public static void openDialog(final String path) {
		View dialogView = mInflater.inflate(R.layout.search, null);
		final EditText editText = dialogView.findViewById(R.id.searchEditText1);
		final ImageView openHistory = dialogView.findViewById(R.id.searchImageView1);
		if (Settings.lightTheme)
			openHistory.setImageResource(R.drawable.ic_collapse);
		else
			openHistory.setImageResource(R.drawable.ic_collapse_dark);
		final List<String> history = searchHistory.getHistory();
		if (history.isEmpty()) {
			openHistory.setVisibility(View.GONE);
		} else {
			editText.setText(history.get(history.size() - 1));
		}
		rb2 = dialogView.findViewById(R.id.searchRadioButton2);
		cb = dialogView.findViewById(R.id.searchCheckBox1);
		cb2 = dialogView.findViewById(R.id.searchCheckBox2);
		rb2.setChecked(Settings.getb(context, "search_rb2", false));
		cb.setChecked(Settings.getb(context, "search_cb", false));
		cb2.setChecked(Settings.getb(context, "search_rec", true));
		final TextView info = dialogView.findViewById(R.id.searchTextView1);
		info.setText(context.getString(R.string.search_info, MUtil.strJoin(textExt, ", ")));
		openHistory.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View p1) {
					PopupMenu menu = new PopupMenu(context, p1);
					int mid = 1400;
					for (int i = history.size(); i > 0; i--) {
						final String hitem = history.get(i - 1);
						MenuItem mitem = menu.getMenu().add(0, mid + i, 0, hitem);
						mitem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
							{
								@Override
								public boolean onMenuItemClick(MenuItem m) {
									editText.setText(hitem);
									return true;
								}
							});
					}
					menu.show();
				}
			});
		openHistory.setOnLongClickListener(new OnLongClickListener() {
				@Override
				public boolean onLongClick(View p1) {
					Runnable clear = new Runnable() {
						@Override
						public void run() {
							searchHistory.clear();
							openHistory.setVisibility(View.GONE);
						}
					};
					MUtil.createDialog(context, context.getString(R.string.clear_history), clear);
					return true;
				}
			});
		AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
		dialogBuilder.setView(dialogView);
		dialogBuilder.setTitle(R.string.search_files);
		dialogBuilder.setPositiveButton(R.string.find, new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface p1, int p2) {
					String need = editText.getText().toString();
					if (TextUtils.isEmpty(need))
						return;
					// Settings.sets(context, "search_text", need);
					Settings.setb(context, "search_cb", cb.isChecked());
					Settings.setb(context, "search_rec", cb2.isChecked());
					Settings.setb(context, "search_rb2", rb2.isChecked());
					searchHistory.putHistory(need);
					new SearchTask().execute(path, need);
				}
			});
		dialogBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface p1, int p2) {
					p1.dismiss();
				}
			});
		dialogBuilder.setNeutralButton(R.string.minfo, null);
		final AlertDialog alertDialog = dialogBuilder.create();
		alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
		alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
				@Override
				public void onShow(DialogInterface dialogInterface) {
					editText.requestFocus();
					editText.selectAll();
					Button button = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL);
					button.setOnClickListener(new View.OnClickListener() {
							@Override
							public void onClick(View view) {
								int vis = info.getVisibility();
								if (vis == View.GONE)
									info.setVisibility(View.VISIBLE);
								else
									info.setVisibility(View.GONE);
							}
						});
				}
			});
		alertDialog.show();
	}

	public static void resultDialog() {
		SearchResult resultView = new SearchResult(context, refresh);
		resultView.setType(!rb2.isChecked());
		resultView.append(mResult);
		AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
		dialogBuilder.setView(resultView);
		dialogBuilder.setTitle(context.getString(R.string.search_result) + " (" + mResult.size() + ")");
		dialogBuilder.setPositiveButton(R.string.close_cur, new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface p1, int p2) {
					p1.dismiss();
				}
			});
		if (mResult.size() > 0) {
			dialogBuilder.setNeutralButton(R.string.search_reset, new DialogInterface.OnClickListener()
				{
					@Override
					public void onClick(DialogInterface p1, int p2) {
						clearResult();
						p1.dismiss();
					}
				});
		}
		AlertDialog alertDialog = dialogBuilder.create();
		resultView.setDialog(alertDialog);
		alertDialog.show();
	}

	public static List<String> listFiles(File dir, String need, boolean ignoreCase, boolean byName, boolean recursive) {
		if (byName) {
			return listFilesByName(dir, need, ignoreCase, recursive);
		} else {
			return listFilesByContent(dir, need, ignoreCase, recursive);
		}
	}

	public static List<String> listFilesByContent(File dir, String need, boolean ignoreCase, boolean recursive) {
		List<String> result = new ArrayList<String>();
		if (stopSearch)
			return result;
		FileFilter dirFilter = new FileFilter() {
			@Override
			public boolean accept(File file) {
				return file.isDirectory();
			}
		};
		FilenameFilter textFilter = new FilenameFilter() {
			@Override
			public boolean accept(File file, String p2) {
				for (String ext : textExt) {
					if (p2.toLowerCase().endsWith("." + ext))
						return true;
				}
				return false;
			}
		};
		File[] files = dir.listFiles(textFilter);
		if (files != null) {
			for (File f : files) {
				if (stopSearch)
					continue;
				if (SearchUtils.indexOf(f, need, ignoreCase))
					result.add(f.getAbsolutePath());
			}
		}
		if (!recursive)
			return result;
		File[] dirs = dir.listFiles(dirFilter);
		if (dirs != null) {
			for (File d : dirs) {
				result.addAll(listFilesByContent(d, need, ignoreCase, recursive));
			}
		}
		return result;
	}

	public static List<String> listFilesByName(File dir, final String need, final boolean ignoreCase, boolean recursive) {
		List<String> result = new ArrayList<String>();
		if (stopSearch)
			return result;
		FileFilter dirFilter = new FileFilter() {
			@Override
			public boolean accept(File file) {
				return file.isDirectory();
			}
		};
		FilenameFilter fileFilter = new FilenameFilter() {
			@Override
			public boolean accept(File file, String p2) {
				if (ignoreCase)
					return p2.toLowerCase().indexOf(need.toLowerCase()) >= 0;
				else
					return p2.indexOf(need) >= 0;
			}
		};
		File[] files = dir.listFiles(fileFilter);
		if (files != null) {
			for (File f : files) {
				if (stopSearch)
					continue;
				result.add(f.getAbsolutePath());
			}
		}
		if (!recursive)
			return result;
		File[] dirs = dir.listFiles(dirFilter);
		if (dirs != null) {
			for (File d : dirs) {
				result.addAll(listFilesByName(d, need, ignoreCase, recursive));
			}
		}
		return result;
	}

	public static void clearResult() {
		mResult = new ArrayList<String>();
	}

	public static boolean isEmpty() {
		return mResult.size() == 0;
	}

	public static class SearchTask extends AsyncTask<String,Long,Boolean> {
		//ProgressDialog progress;
		AlertDialog dialog;

		@Override
		protected void onPreExecute() {
			//progress = ProgressDialog.show(context, "", context.getString(R.string.search_files), true);
			stopSearch = false;
			View dialogView = mInflater.inflate(R.layout.search_progress, null);
			dialog = new AlertDialog.Builder(context)
				.setView(dialogView)
				.setPositiveButton(R.string.cancel, new DialogInterface.OnClickListener()
				{
					@Override
					public void onClick(DialogInterface p1, int p2) {
						stopSearch = true;
						cancel(true);
						p1.dismiss();
					}
				})
				.create();
			dialog.show();
		}

		@Override
		protected Boolean doInBackground(String... str) {
			mResult = listFiles(new File(str[0]), str[1], !cb.isChecked(), !rb2.isChecked(), cb2.isChecked());
			return true;
		}

		@Override
		protected void onPostExecute(Boolean success) {
			//progress.dismiss();
			dialog.dismiss();
			resultDialog();
		}

		@Override
		protected void onCancelled(Boolean result) {
			super.onCancelled(result);
			resultDialog();
		}
	}
}
